home *** CD-ROM | disk | FTP | other *** search
/ Computer Idee 14 / Computer Idee 14-01.iso / COMICIT / ComicIt.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-07-09  |  16.4 KB  |  404 lines

  1. // Name: ComicIt. Converts rough scans of comics into more sharp and colour consistant pictures.
  2. // Copyright (C) 1999 S°ren Krarup Olesen
  3.  
  4. // This program is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU General Public License
  6. // as published by the Free Software Foundation; either version 2
  7. // of the License, or (at your option) any later version.
  8.  
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. // GNU General Public License for more details.
  13.  
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program; if not, write to the Free Software
  16. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  
  18. // Please contact me at e-mail sko@kom.auc.dk for questions or comments.
  19.  
  20. #include <math.h>
  21. #define STRICT
  22. #include <windows.h>
  23. #include "ComicIt.h"
  24.  
  25. BOOL bRunningFirstTime=FALSE;
  26.  
  27. struct col {
  28.    BYTE cRed;
  29.    BYTE cGreen;
  30.    BYTE cBlue;
  31. };
  32.  
  33. class SetupGroup {
  34.    HKEY hKey;
  35.    DWORD dwType,dwSize,dwWhatHappened;
  36. public:
  37.    Line szInputFile;
  38.    int nBlackSize;
  39.    int nEdgeSize;
  40.    BOOL bStandAlone;
  41.    int nDepth;
  42.    int nDarkSize;
  43.    int nLightSize;
  44.    Line szOutputFile;
  45.    SetupGroup();
  46.    void init(),save_in_registry(),load_from_registry();
  47. };
  48.  
  49. SetupGroup::SetupGroup() {
  50.    RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\ComicIt",0,"SKOClass",REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,&dwWhatHappened);
  51.    lstrcpy(szInputFile,"input.bmp");
  52.    nBlackSize=35;
  53.    nEdgeSize=12;
  54.    bStandAlone=TRUE;
  55.    nDepth=3;
  56.    nDarkSize=12;
  57.    nLightSize=100;
  58.    lstrcpy(szOutputFile,"output.bmp");
  59.    if (dwWhatHappened==REG_CREATED_NEW_KEY) {
  60.       bRunningFirstTime=TRUE;
  61.       save_in_registry();
  62.    }
  63.    else load_from_registry();
  64.    RegCloseKey(hKey);
  65.    hKey=NULL;
  66. }
  67.  
  68. void SetupGroup::save_in_registry() {
  69.    if (!hKey) RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\ComicIt",0,"SKOClass",REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,&dwWhatHappened);
  70.    RegSetValueEx(hKey,"Input file",0,REG_SZ,(CONST LPBYTE)szInputFile,LINE_LEN+1);
  71.    RegSetValueEx(hKey,"Black size",0,REG_DWORD,(CONST LPBYTE)(&nBlackSize),sizeof(nBlackSize));
  72.    RegSetValueEx(hKey,"Edge size",0,REG_DWORD,(CONST LPBYTE)(&nEdgeSize),sizeof(nEdgeSize));
  73.    RegSetValueEx(hKey,"Stand alone",0,REG_DWORD,(CONST LPBYTE)(&bStandAlone),sizeof(bStandAlone));
  74.    RegSetValueEx(hKey,"Depth",0,REG_DWORD,(CONST LPBYTE)(&nDepth),sizeof(nDepth));
  75.    RegSetValueEx(hKey,"Dark size",0,REG_DWORD,(CONST LPBYTE)(&nDarkSize),sizeof(nDarkSize));
  76.    RegSetValueEx(hKey,"Light size",0,REG_DWORD,(CONST LPBYTE)(&nLightSize),sizeof(nLightSize));
  77.    RegSetValueEx(hKey,"Output file",0,REG_SZ,(CONST LPBYTE)szOutputFile,LINE_LEN+1);
  78.    if (hKey) RegCloseKey(hKey);
  79. }
  80.  
  81. void SetupGroup::load_from_registry() {
  82.    if (!hKey) RegCreateKeyEx(HKEY_CURRENT_USER,"Software\\ComicIt",0,"SKOClass",REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,&dwWhatHappened);
  83.    while (RegQueryValueEx(hKey,"Input file",0,&dwType,(LPBYTE)szInputFile,&dwSize)!=ERROR_SUCCESS);
  84.    while (RegQueryValueEx(hKey,"Black size",0,&dwType,(LPBYTE)(&nBlackSize),&dwSize)!=ERROR_SUCCESS);
  85.    while (RegQueryValueEx(hKey,"Edge size",0,&dwType,(LPBYTE)(&nEdgeSize),&dwSize)!=ERROR_SUCCESS);
  86.    while (RegQueryValueEx(hKey,"Stand alone",0,&dwType,(LPBYTE)(&bStandAlone),&dwSize)!=ERROR_SUCCESS);
  87.    while (RegQueryValueEx(hKey,"Depth",0,&dwType,(LPBYTE)(&nDepth),&dwSize)!=ERROR_SUCCESS);
  88.    while (RegQueryValueEx(hKey,"Dark size",0,&dwType,(LPBYTE)(&nDarkSize),&dwSize)!=ERROR_SUCCESS);
  89.    while (RegQueryValueEx(hKey,"Light size",0,&dwType,(LPBYTE)(&nLightSize),&dwSize)!=ERROR_SUCCESS);
  90.    while (RegQueryValueEx(hKey,"Output file",0,&dwType,(LPBYTE)szOutputFile,&dwSize)!=ERROR_SUCCESS);
  91.    if (hKey) RegCloseKey(hKey);
  92. }
  93.  
  94. BOOL error(HWND hDlg,LPSTR szErrorMessage) {
  95.    MessageBox(hDlg,szErrorMessage,"Error",MB_ICONERROR);
  96.    return FALSE;
  97. }
  98.  
  99. double len(struct col &p) {
  100.    double x1,x2,x3,res;
  101.    x1=(double)p.cRed;
  102.    x2=(double)p.cGreen;
  103.    x3=(double)p.cBlue;
  104.    res=sqrt(x1*x1+x2*x2+x3*x3);
  105.    return res;
  106. }
  107.  
  108. BOOL is_black(struct col &p) {
  109.    if ((p.cRed==0) && (p.cGreen==0) && (p.cBlue==0)) return TRUE;
  110.    else return FALSE;
  111. }
  112.  
  113. BOOL is_white(struct col &p) {
  114.    if ((p.cRed==255) && (p.cGreen==255) && (p.cBlue==255)) return TRUE;
  115.    else return FALSE;
  116. }
  117.  
  118. void diff(struct col &in1,struct col &in2,struct col &out) {
  119.    out.cRed=(BYTE)fabs((double)in1.cRed-in2.cRed);
  120.    out.cGreen=(BYTE)fabs((double)in1.cGreen-in2.cGreen);
  121.    out.cBlue=(BYTE)fabs((double)in1.cBlue-in2.cBlue);
  122. }
  123.  
  124. BOOL convert(HWND hDlg,SetupGroup &sg) {
  125.    HANDLE hFile;
  126.    BITMAPFILEHEADER bmfh;
  127.    BITMAPINFOHEADER bmih;
  128.    DWORD dwDummy,dwFileSize,dwPictureSize,dwActualPictureSize,dwRed,dwGreen,dwBlue,dwNumberOfAvgPixels;
  129.    LONG i,j,k,lExtraBytesPerLine,lBegin,lEnd;
  130.    BYTE cDummy;
  131.    struct col **p,**q,**r;
  132.  
  133.    SetDlgItemText(hDlg,IDC_STATUS,"Importing BMP file...");
  134.  
  135.    hFile=CreateFile(sg.szInputFile,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  136.    if (hFile==INVALID_HANDLE_VALUE) return error(hDlg,"Cannot open input file");
  137.    dwFileSize=GetFileSize(hFile,NULL);
  138.    ReadFile(hFile,&bmfh,sizeof(bmfh),&dwDummy,NULL);
  139.    if (bmfh.bfType!=19778) {
  140.       CloseHandle(hFile);
  141.       return error(hDlg,"Input is not a BMP file");
  142.    }
  143.    if (bmfh.bfSize!=dwFileSize) { // DWORD
  144.       CloseHandle(hFile);
  145.       return error(hDlg,"Wrong file size field in BMP file");
  146.    }
  147.    if (bmfh.bfReserved1||bmfh.bfReserved2) {
  148.       if (MessageBox(hDlg,"Unexpected content in reserved\nfields in BMP file.\n\nDo you want to continue?","Warning",MB_ICONWARNING|MB_YESNO)==IDNO) {
  149.          CloseHandle(hFile);
  150.          return FALSE;
  151.       }
  152.    }
  153.    ReadFile(hFile,&bmih,sizeof(bmih),&dwDummy,NULL);
  154.    if ((bmih.biWidth<32)||(bmih.biHeight)<32) { // LONG - LONG
  155.       CloseHandle(hFile);
  156.       return error(hDlg,"The BMP file is too small for conversion");
  157.    }
  158.    if (bmih.biPlanes!=1) {
  159.       CloseHandle(hFile);
  160.       return error(hDlg,"Unsupported number of planes in BMP file");
  161.    }
  162.    if (bmih.biBitCount!=24) {
  163.       CloseHandle(hFile);
  164.       return error(hDlg,"The input BMP file must be 24 bits");
  165.    }
  166.    if (bmih.biCompression!=BI_RGB) {
  167.       CloseHandle(hFile);
  168.       return error(hDlg,"The input BMP file must not be compressed");
  169.    }
  170.    dwPictureSize=dwFileSize-sizeof(bmfh)-sizeof(bmih);
  171.    if (dwPictureSize%bmih.biHeight) {
  172.       CloseHandle(hFile);
  173.       return error(hDlg,"Picture size is not dividable\nby the number of scan lines");
  174.    }
  175.    dwActualPictureSize=bmih.biWidth*bmih.biHeight*3;
  176.    lExtraBytesPerLine=(dwPictureSize-dwActualPictureSize)/bmih.biHeight;
  177.    p=new struct col *[bmih.biWidth];
  178.    if (!p) FatalAppExit(0,"Not enough memory");
  179.    for (i=0; i<bmih.biWidth; i++) {
  180.       p[i]=new struct col[bmih.biHeight];
  181.       if (!p[i]) FatalAppExit(0,"Not enough memory");
  182.    }
  183.    for (j=0; j<bmih.biHeight; j++) {
  184.       for (i=0; i<bmih.biWidth; i++) ReadFile(hFile,&p[i][j],3,&dwDummy,NULL);
  185.       for (i=0; i<lExtraBytesPerLine; i++) ReadFile(hFile,&cDummy,1,&dwDummy,NULL);
  186.    }
  187.    CloseHandle(hFile);   
  188.    
  189.    SetDlgItemText(hDlg,IDC_STATUS,"Mark-up regions...");
  190.    
  191.    q=new struct col *[bmih.biWidth];
  192.    if (!q) FatalAppExit(0,"Not enough memory");
  193.    for (i=0; i<bmih.biWidth; i++) {
  194.       q[i]=new struct col[bmih.biHeight];
  195.       if (!q[i]) FatalAppExit(0,"Not enough memory");
  196.    }
  197.  
  198.    for (j=0; j<bmih.biHeight; j++) for (i=0; i<bmih.biWidth; i++) q[i][j].cRed=q[i][j].cGreen=q[i][j].cBlue=255;
  199.  
  200.    for (j=0; j<bmih.biHeight; j++) for (i=0; i<bmih.biWidth; i++) if (len(p[i][j])<(441.68*(sg.nBlackSize/100.0))) q[i][j].cRed=q[i][j].cGreen=q[i][j].cBlue=0;
  201.    struct col c1,c2,c3;
  202.    for (j=1; j<bmih.biHeight-1; j++) {
  203.       for (i=1; i<bmih.biWidth-1; i++) {
  204.          diff(p[i-1][j],p[i][j],c1);
  205.          diff(p[i][j-1],p[i][j],c2);
  206.          if (len(c1)>len(c2)) c3=c1; // Finds the largest value--either H or V. Could also use the divergence?!
  207.          else c3=c2;
  208.          if (len(c3)>(441.68*(sg.nEdgeSize/100.0))) q[i][j].cRed=q[i][j].cGreen=q[i][j].cBlue=0;
  209.       }
  210.    }
  211.  
  212.    SetDlgItemText(hDlg,IDC_STATUS,"Noise reduction...");
  213.  
  214.    if (sg.bStandAlone) {
  215.       for (j=1; j<bmih.biHeight-1; j++)
  216.          for (i=1; i<bmih.biWidth-1; i++)
  217.             if (is_black(q[i][j]))
  218.                if (is_white(q[i-1][j]) && is_white(q[i+1][j]) && is_white(q[i][j-1]) && is_white(q[i][j+1]))
  219.                   q[i][j].cRed=q[i][j].cGreen=q[i][j].cBlue=255;
  220.    }            
  221.  
  222.    SetDlgItemText(hDlg,IDC_STATUS,"Save b/w picture...");
  223.    
  224.    hFile=CreateFile("bw.bmp",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  225.    if (hFile==INVALID_HANDLE_VALUE) return error(hDlg,"Cannot open b/w file");
  226.    WriteFile(hFile,&bmfh,sizeof(bmfh),&dwDummy,NULL);
  227.    WriteFile(hFile,&bmih,sizeof(bmih),&dwDummy,NULL);
  228.    cDummy='\0';
  229.    for (j=0; j<bmih.biHeight; j++) {
  230.       for (i=0; i<bmih.biWidth; i++) WriteFile(hFile,&q[i][j],3,&dwDummy,NULL);
  231.       for (i=0; i<lExtraBytesPerLine; i++) WriteFile(hFile,&cDummy,1,&dwDummy,NULL);
  232.    }
  233.    CloseHandle(hFile);   
  234.  
  235.    SetDlgItemText(hDlg,IDC_STATUS,"Colour averaging...");
  236.  
  237.    r=new struct col *[bmih.biWidth];
  238.    if (!r) FatalAppExit(0,"Not enough memory");
  239.    for (i=0; i<bmih.biWidth; i++) {
  240.       r[i]=new struct col[bmih.biHeight];
  241.       if (!r[i]) FatalAppExit(0,"Not enough memory");
  242.    }
  243.    for (j=0; j<bmih.biHeight; j++) {
  244.       for (i=1; i<bmih.biWidth; i++) {
  245.          r[i][j].cRed=p[i][j].cRed;
  246.          r[i][j].cGreen=p[i][j].cGreen;
  247.          r[i][j].cBlue=p[i][j].cBlue;
  248.       }
  249.    }
  250.    for (k=0; k<sg.nDepth; k++) {
  251.       // Vertical:   
  252.       bmih.biHeight--;
  253.       for (j=0; j<bmih.biWidth; j++) {
  254.          lBegin=lEnd=0;
  255.          while (1) {
  256.             for (lEnd=lBegin; (is_white(q[j][lEnd]) && lEnd<bmih.biHeight); lEnd++);
  257.             dwRed=dwGreen=dwBlue=0;
  258.             for (i=lBegin; i<lEnd; i++) {
  259.                dwRed+=r[j][i].cRed;
  260.                dwGreen+=r[j][i].cGreen;
  261.                dwBlue+=r[j][i].cBlue;
  262.             }
  263.             dwNumberOfAvgPixels=lEnd-lBegin;
  264.             if (!dwNumberOfAvgPixels) goto next_try2;
  265.             dwRed/=dwNumberOfAvgPixels;
  266.             dwGreen/=dwNumberOfAvgPixels;
  267.             dwBlue/=dwNumberOfAvgPixels;
  268.             for (i=lBegin; i<lEnd; i++) {
  269.                r[j][i].cRed=(BYTE)dwRed;
  270.                r[j][i].cGreen=(BYTE)dwGreen;
  271.                r[j][i].cBlue=(BYTE)dwBlue;
  272.             }
  273.             next_try2:
  274.             lBegin=lEnd+1; // perhaps +1
  275.             if (lBegin>=bmih.biHeight) break; // EOL reached
  276.          }
  277.       }
  278.       bmih.biHeight++;
  279.       // Horizontal:
  280.       bmih.biWidth--;
  281.       for (j=0; j<bmih.biHeight; j++) {
  282.          lBegin=lEnd=0;
  283.          while (1) {
  284.             for (lEnd=lBegin; (is_white(q[lEnd][j]) && lEnd<bmih.biWidth); lEnd++);
  285.             dwRed=dwGreen=dwBlue=0;
  286.             for (i=lBegin; i<lEnd; i++) {
  287.                dwRed+=r[i][j].cRed;
  288.                dwGreen+=r[i][j].cGreen;
  289.                dwBlue+=r[i][j].cBlue;
  290.             }
  291.             dwNumberOfAvgPixels=lEnd-lBegin;
  292.             if (!dwNumberOfAvgPixels) goto next_try1;
  293.             dwRed/=dwNumberOfAvgPixels;
  294.             dwGreen/=dwNumberOfAvgPixels;
  295.             dwBlue/=dwNumberOfAvgPixels;
  296.             for (i=lBegin; i<lEnd; i++) {
  297.                r[i][j].cRed=(BYTE)dwRed;
  298.                r[i][j].cGreen=(BYTE)dwGreen;
  299.                r[i][j].cBlue=(BYTE)dwBlue;
  300.             }
  301.             next_try1:
  302.             lBegin=lEnd+1;
  303.             if (lBegin>=bmih.biWidth) break;
  304.          }
  305.       }
  306.       bmih.biWidth++;
  307.    }
  308.  
  309.    SetDlgItemText(hDlg,IDC_STATUS,"Final b/w tuning...");
  310.    
  311.    for (j=0; j<bmih.biHeight; j++) for (i=0; i<bmih.biWidth; i++) if (len(p[i][j])<(441.68*(sg.nDarkSize/100.0))) r[i][j].cRed=r[i][j].cGreen=r[i][j].cBlue=0;
  312.    for (j=0; j<bmih.biHeight; j++) for (i=0; i<bmih.biWidth; i++) if (len(p[i][j])>(441.68*(sg.nLightSize/100.0))) r[i][j].cRed=r[i][j].cGreen=r[i][j].cBlue=255;
  313.  
  314.    SetDlgItemText(hDlg,IDC_STATUS,"Save output picture...");
  315.    
  316.    hFile=CreateFile(sg.szOutputFile,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  317.    if (hFile==INVALID_HANDLE_VALUE) return error(hDlg,"Cannot open output file");
  318.    WriteFile(hFile,&bmfh,sizeof(bmfh),&dwDummy,NULL);
  319.    WriteFile(hFile,&bmih,sizeof(bmih),&dwDummy,NULL);
  320.    cDummy='\0';
  321.    for (j=0; j<bmih.biHeight; j++) {
  322.       for (i=0; i<bmih.biWidth; i++) WriteFile(hFile,&r[i][j],3,&dwDummy,NULL);
  323.       for (i=0; i<lExtraBytesPerLine; i++) WriteFile(hFile,&cDummy,1,&dwDummy,NULL);
  324.    }
  325.    CloseHandle(hFile);   
  326.    
  327.    for (i=0; i<bmih.biWidth; i++) delete r[i];
  328.    delete r;
  329.    for (i=0; i<bmih.biWidth; i++) delete q[i];
  330.    delete q;
  331.    for (i=0; i<bmih.biWidth; i++) delete p[i];
  332.    delete p;
  333.    return TRUE;
  334. }
  335.  
  336. BOOL invalid_vector_size(HWND hDlg,int nSize) {
  337.    if ((nSize>=0)&&(nSize<=100)) return FALSE;
  338.    MessageBox(hDlg,"The length of an RGB vector should be kept\nbetween 0 and 100%, where 0 corresponds\nto RGB=0,0,0 (length=0) and 100% corresponds\nto RGB=255,255,255 (length=442)","Range error",MB_ICONERROR);
  339.    return TRUE;
  340. }
  341.  
  342. BOOL CALLBACK MainProc(HWND hDlg,UINT wMsg,WPARAM wParam,LPARAM) {
  343.    static SetupGroup sg;
  344.    static SetupGroup _sg;
  345.    switch (wMsg) {
  346.       case WM_INITDIALOG:
  347.          if (bRunningFirstTime) MessageBox(hDlg,"ComicIt version 1.0, Copyright (C) 1999 S°ren Krarup Olesen\nComicIt comes with ABSOLUTELY NO WARRANTY; for details\nsee the file gpl.txt. This is free software, and you are welcome\nto redistribute it under certain conditions; see the file gpl.txt for details.","License",MB_ICONINFORMATION);
  348.          SetDlgItemText(hDlg,IDC_INPUT_FILE,sg.szInputFile);          
  349.          SetDlgItemInt(hDlg,IDC_BLACK_SIZE,sg.nBlackSize,TRUE);
  350.          SetDlgItemInt(hDlg,IDC_EDGE_SIZE,sg.nEdgeSize,TRUE);          
  351.          if (sg.bStandAlone) SendDlgItemMessage(hDlg,IDC_STAND_ALONE,BM_SETCHECK,BST_CHECKED,0);
  352.          else SendDlgItemMessage(hDlg,IDC_STAND_ALONE,BM_SETCHECK,BST_UNCHECKED,0);
  353.          if (sg.nDepth==1) SendDlgItemMessage(hDlg,IDC_DEPTH_1,BM_SETCHECK,BST_CHECKED,0);
  354.          else if (sg.nDepth==2) SendDlgItemMessage(hDlg,IDC_DEPTH_2,BM_SETCHECK,BST_CHECKED,0);
  355.          else SendDlgItemMessage(hDlg,IDC_DEPTH_3,BM_SETCHECK,BST_CHECKED,0);          
  356.          SetDlgItemInt(hDlg,IDC_DARK_SIZE,sg.nDarkSize,TRUE);                   
  357.          SetDlgItemInt(hDlg,IDC_LIGHT_SIZE,sg.nLightSize,TRUE);
  358.          SetDlgItemText(hDlg,IDC_OUTPUT_FILE,sg.szOutputFile);          
  359.          _sg=sg;
  360.          break;
  361.       case WM_COMMAND:
  362.          switch (LOWORD(wParam)) {
  363.             case IDC_CONVERT:
  364.                GetDlgItemText(hDlg,IDC_INPUT_FILE,_sg.szInputFile,LINE_LEN);
  365.                _sg.nBlackSize=GetDlgItemInt(hDlg,IDC_BLACK_SIZE,NULL,TRUE);
  366.                if (invalid_vector_size(hDlg,_sg.nBlackSize)) break;
  367.                _sg.nEdgeSize=GetDlgItemInt(hDlg,IDC_EDGE_SIZE,NULL,TRUE);                
  368.                if (invalid_vector_size(hDlg,_sg.nEdgeSize)) break;                
  369.                if (SendDlgItemMessage(hDlg,IDC_STAND_ALONE,BM_GETCHECK,0,0)==BST_CHECKED) _sg.bStandAlone=TRUE;
  370.                else _sg.bStandAlone=FALSE;
  371.                if (SendDlgItemMessage(hDlg,IDC_DEPTH_1,BM_GETCHECK,0,0)==BST_CHECKED) _sg.nDepth=1;
  372.                else if (SendDlgItemMessage(hDlg,IDC_DEPTH_2,BM_GETCHECK,0,0)==BST_CHECKED) _sg.nDepth=2;
  373.                else _sg.nDepth=3;
  374.                _sg.nDarkSize=GetDlgItemInt(hDlg,IDC_DARK_SIZE,NULL,TRUE);                
  375.                if (invalid_vector_size(hDlg,_sg.nDarkSize)) break;                
  376.                _sg.nLightSize=GetDlgItemInt(hDlg,IDC_LIGHT_SIZE,NULL,TRUE);                
  377.                if (invalid_vector_size(hDlg,_sg.nLightSize)) break;                
  378.                GetDlgItemText(hDlg,IDC_OUTPUT_FILE,_sg.szOutputFile,LINE_LEN);               
  379.                if (convert(hDlg,_sg)) sg=_sg;
  380.                SetDlgItemText(hDlg,IDC_STATUS,"OK");
  381.                break;
  382.             case IDC_EXIT:
  383.                sg.save_in_registry();
  384.                EndDialog(hDlg,FALSE);
  385.                break;
  386.             default:
  387.                return FALSE;
  388.          }
  389.          break;
  390.       case WM_CLOSE:
  391.          sg.save_in_registry();
  392.          EndDialog(hDlg,FALSE);
  393.          break;
  394.       default:
  395.          return FALSE;
  396.    }
  397.    return TRUE;
  398. }
  399.  
  400. WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpszCmdLine,int nCmdShow) {
  401.    DialogBox(hInst,"MAIN",HWND_DESKTOP,MainProc);
  402.    return FALSE;
  403. }
  404.